﻿#region Usings

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Caching;
using System.Web.Mvc;
using Ninject;
using Rail.Net.Common;
using Rail.Net.Common.Model;
using Rail.Net.Common.Resources;
using Rail.Net.Core.Interfaces.Services;
using Rail.Net.Core.Model.Nonpersistent;

#endregion

namespace Rail.Net.Controllers
{
    public class TicketController : BaseController
    {
        private readonly Object _lock = new Object();

        [Inject]
        public IProductService ProductServiceOutwards { get; set; }

        [Inject]
        public IProductService ProductServiceReturn { get; set; }

        public ActionResult Selection()
        {
            return View(new SearchModel());
        }

        [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
        public void OffersAsync(SearchModel model)
        {
            // fix the traveler and station names
            model.FixDropdownListNames(Session[Constants.FromStationsCookie] as List<NameValuePair>, Session[Constants.ToStationsCookie] as List<NameValuePair>);

            Session[Constants.SearchModelCookie] = model;
            
            // clear previous products
            Session[Constants.FromProductOffersCookie] = null;
            Session[Constants.ToProductOffersCookie] = null;

            AsyncManager.OutstandingOperations.Increment(model.ToDate.HasValue ? 2 : 1);

            var offersModel = new OffersModel { SearchModel = model };

            var worker1 = new BackgroundWorker();
            worker1.DoWork += (o, e) =>
            {
                try
                {
                    var productOfferModel = ProductServiceOutwards.GetProductOffer(model, true);

                    // save the product offers into the session
                    Session[Constants.FromProductOffersCookie] = productOfferModel;

                    lock (_lock)
                    {
                        AsyncManager.Parameters["offersModel"] = offersModel;
                        AsyncManager.Parameters["forwardProducts"] = productOfferModel;
                    }
                }
                catch (Exception ex)
                {
                    var i = 9;
                }
            };
            worker1.RunWorkerCompleted += (o, e) => AsyncManager.OutstandingOperations.Decrement();
            worker1.RunWorkerAsync();

            if (model.ToDate.HasValue)
            {
                var worker2 = new BackgroundWorker();
                worker2.DoWork += (o, e) =>
                {
                    try
                    {
                        var productOfferModel = ProductServiceReturn.GetProductOffer(model, false);
                        
                        // save the product offers into the session
                        Session[Constants.ToProductOffersCookie] = productOfferModel;

                        lock (_lock)
                        {
                            AsyncManager.Parameters["returnProducts"] = productOfferModel;
                        }
                    }
                    catch (Exception ex)
                    {
                        var i = 9;
                    }
                };
                worker2.RunWorkerCompleted += (o, e) => AsyncManager.OutstandingOperations.Decrement();
                worker2.RunWorkerAsync();
            }
        }

        public ActionResult OffersCompleted(OffersModel offersModel, ProductOfferModel forwardProducts,
                                            ProductOfferModel returnProducts)
        {
            if (forwardProducts != null)
            {
                offersModel.ForwardDirectionProducts = forwardProducts;
            }
            if (returnProducts != null)
            {
                offersModel.ReturnDirectionProducts = returnProducts;
            }
            return PartialView("Offers", offersModel);
        }

        [HttpPost]
        public ActionResult ClientData(int outwardProductId, int? returnProductId)
        {
            //ModelState.Clear();
            var model = new ClientDataModel
                            {
                                OutwardProductId = outwardProductId
                            };
            if (returnProductId.HasValue)
            {
                model.ReturnProductId = returnProductId.Value;
            }
            var sessionActive = true;
            var searchModel = Session[Constants.SearchModelCookie] as SearchModel;
            if (searchModel == null)
            {
                sessionActive = false;
            }
            model.SearchModel = searchModel;

            var productOfferModel = Session[Constants.FromProductOffersCookie] as ProductOfferModel;
            if (productOfferModel != null)
            {
                var product = productOfferModel.Products.SingleOrDefault(p => p.Index == model.OutwardProductId);
                model.OutwardProduct = product;
            }
            else
            {
                sessionActive = false;
            }

            if (returnProductId.HasValue)
            {
                productOfferModel = Session[Constants.ToProductOffersCookie] as ProductOfferModel;
                if (productOfferModel != null)
                {
                    var product = productOfferModel.Products.SingleOrDefault(p => p.Index == model.ReturnProductId);
                    model.ReturnProduct = product;
                }
            }

            if (sessionActive)
            {
                return PartialView(model);
            }
            return Content(Global.Main_SessionTimeout);
        }

        [HttpPost]
        public ActionResult Payment(ClientDataModel model)
        {
            return Content("Welcome to payment");
        }

        

        public ActionResult About()
        {
            return View();
        }

        public ActionResult Error()
        {
            return View();
        }
    }
}